/*
    The MIT License

    Copyright (c) 2010 IFMO/GameDev Studio

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#pragma once

/*-----------------------------------------------------------------------------
	Water rendering :
-----------------------------------------------------------------------------*/
#include "gl_local.h"
#include "fr_local.h"
#include <cuda_runtime.h>
//#include <cutil_inline.h>
//#include <cutil_gl_inline.h>
//#include <cutil_gl_error.h>
#include <cuda_gl_interop.h>
#include <cufft.h>
#include <math_constants.h>

struct WakeDrop;
struct WakeBufInfo;
//#include "water_cu.h"



class EFRWater : public ICoreObject {
	public:
							EFRWater			( EFRScene *scene, const EString &mesh, const EString &noise, float omega, float scale, float falloff );
							~EFRWater			( void );
							
		void				SetTime				( float time );
		void				ReloadShader		( void );
		void				Render				( EFrame frame, EGBuffer gbuf );
		
		void				GetWaterDynamics	( const EPoint &pos, float &pressure, float &surface_level, EVector &velocity ) const;
		void				MakeWaterDrop		( const EPoint &pos, float offset );

	protected:
		
		static int			set_spectra			( lua_State *L );
		static int			set_sine			( lua_State *L );
		static int			set_spectra_wind	( lua_State *L );
		static int			get_wave_height		( lua_State *L );
	
	
		static EFRWater		*self;
		
		void				init_cuda_fft_water		( void );
		void				kill_cuda_fft_water		( void );
		void				update_cuda_fft_water	( void );
		void				create_init_spectra		( void );
		float				spectraPM				( float w );
		float				spectraPM				( float w, float n );
		float				spectra_power_ratio		( float n );
		float				spectraPM_k				( float k );
		float				jonswap					( float w );
		float				distrib_integral		( void );
		float				normalize_spectra		( void );
		float				amplitude_1d			( float k );
		float				amplitude_2d			( float kx, float ky );
		IPxTexture			waves_tex;
		cufftHandle			plan;
		cufftComplex		*idata;
		cufftComplex		*idatat;

		GLuint					wave_buf_gl;
		cudaGraphicsResource	*wave_buf_cuda;
		std::vector<float2>		wave_data;
		std::vector<float2>		wave_data_old;
		
		void				init_wakes				( void );
		void				kill_wakes				( void );
		void				update_wakes			( void );
		std::vector<WakeDrop> drop_accum;
		WakeDrop			*d_drop_pool;
		
		std::vector<WakeBufInfo>	wake_buf_cuda;
		int					cur_wake_buf;
		IPxTexture			wakes_tex[2];
		cudaGraphicsResource *wakes_tex_cuda[2];
		EPoint				wake_center;


		float2 sample_wave_data ( int x, int y ) const;
		float2 sample_wave_data_f ( float x, float y ) const;
		float	peak_frequency;
		float	narrowness;
		float	jonswap_gamma;
		float	spectra_norm;

		float	w_cutoff;
		float	k_cutoff;
		float	dk;
		float	spatial_period;

		float	dump_time;
	
		//
		//	sky :
		//
		IPxFREntity			r_sky;		
		
		//
		//	rendering stuff :
		//
		bool				enabled;
	
		EFRScene	*scene;
	
		IPxEffect			water_fx;
		IPxTriMesh			water_mesh;
		IPxVertexBuffer		water_vb;
		IPxTriMesh			water_back_mesh;
		IPxVertexBuffer		water_back_vb;
		
		IPxTexture			noise_tx;
		IPxTexture			foam_tx;
		
		IPxRTManager		rtm;
		IPxTXManager		txm;
		IPxVBManager		vbm;
		
		struct {
			float time;
			float delta_time;
		} wavegen;
		
		IPxVar				fr_water_debug;

		uint water_seed;
	};
